// #include "../include/redis.h"
#include "redis.h"

Redis::Redis() {
    initCommandTypes();
}
Redis::~Redis() {

}

std::string Redis::command(const std::string &command)
{
    std::istringstream iss(command);
    std::string type, key;
    iss >> type;
    iss >> key;
    if (type.empty() || key.empty()) {
        std::cout << "Wrong command" << std::endl;
        return " ";
    }

    DataModel* model = nullptr;
    if (redis.count(key) == 0) {
        model = plantDataModel(type);
        if (model == nullptr){
            std::cout <<"( mistake )" << std::endl;
            return "mistake";
        }
        redis[key] = model;
    } else {
        model = redis[key];
    }

    std::string result = model->executeCommand(type, iss);
    // std::cout << "result: " << result << std::endl;
    return result;
}


DataModel *Redis::plantDataModel(const std::string &type){
    if (commandTypes.count(type) == 0) {
        return nullptr;
    }
    RedisDataType redisDataType = commandTypes[type];
    switch (redisDataType)
    {
    case RedisDataType::STRING:
        // std::cout << "plant string data model ";
        return new StringDataModel();
    case RedisDataType::HASH:
        // std::cout << "plant hash data model ";
        return new HashDataModel();
    case RedisDataType::LIST:
        // std::cout << "plant list data model ";
        return new ListDataModel();
    case RedisDataType::SET:
        // std::cout << "plant set data model ";
        return new SetDataModel();  
    default:
        // std::cout << "no data model found for type: " << type << std::endl;
        return nullptr;
    }
    return nullptr;
}

void Redis::initCommandTypes()
{
    commandTypes["set"] = RedisDataType::STRING;
    commandTypes["hash"] = RedisDataType::HASH;
    commandTypes["lpush"] = RedisDataType::LIST;
    commandTypes["rpush"] = RedisDataType::LIST;
    commandTypes["sadd"] = RedisDataType::SET;

    // commandTypes["get"] = RedisDataType::STRING;
    // commandTypes["hget"] = RedisDataType::HASH;
    // commandTypes["lrange"] = RedisDataType::LIST;
    // commandTypes["smembers"] = RedisDataType::SET;
}